package com.guqj.nio.netty.pstack.client;

import io.netty.channel.ChannelHandlerAppender;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.ScheduledFuture;

import java.util.concurrent.TimeUnit;

import com.guqj.nio.netty.pstack.pojo.Header;
import com.guqj.nio.netty.pstack.pojo.MessageType;
import com.guqj.nio.netty.pstack.pojo.NettyMessage;

/**
 * 心跳检查-请求端
 * 
 * @author guqj
 * @date 2016年11月28日
 */
public class HeartBeatReqHandler extends ChannelHandlerAppender {

	private volatile ScheduledFuture<?> heartBeat;

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		if (heartBeat != null) {
			heartBeat.cancel(true);
			heartBeat = null;
		}
		ctx.fireExceptionCaught(cause);
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		NettyMessage message = (NettyMessage) msg;
		// 如果是登录响应，则建立心跳检测
		if (message.getHeader() != null && message.getHeader().getType() == MessageType.LOGIN_RESP.value()) {
			heartBeat = ctx.executor().scheduleAtFixedRate(new HeartBeatReqHandler.HeartBeatTask(ctx), 0, 5000,
					TimeUnit.MICROSECONDS); // 定时发送心跳检测信息
		} else if (message.getHeader() != null && message.getHeader().getType() == MessageType.HEARTBEAT_RESP.value()) {// 收到心跳检测响应
			System.out.println("Client receive server heart beat message:" + message);
		} else {
			ctx.fireChannelRead(msg);
		}
	}

	class HeartBeatTask implements Runnable {
		private final ChannelHandlerContext ctx;

		public HeartBeatTask(final ChannelHandlerContext ctx) {
			this.ctx = ctx;
		}

		@Override
		public void run() {
			NettyMessage message = buildHeartBeat();
			System.out.println("Client send heart beat message: " + message);
			ctx.writeAndFlush(message);
		}

		private NettyMessage buildHeartBeat() {
			NettyMessage message = new NettyMessage();
			Header header = new Header();
			header.setType(MessageType.HEARTBEAT_REQ.value());
			message.setHeader(header);
			return message;
		}
	}
}
